﻿using DeviceFaultPushService.DeviceProcessManagement.CommunicationManagement.ModbusTcp.Models;
using DeviceFaultPushService.DeviceProcessManagement.CommunicationManagement.Models;
using DeviceFaultPushService.MessagePushService.Models;
using NModbus;
using System.Net.Sockets;

namespace DeviceFaultPushService.DeviceProcessManagement.CommunicationManagement.ModbusTcp;

public class DeviceCommunication(Models.DeviceInformationModel deviceInformation) : IDeviceCommunication
{
    private IModbusMaster master;

    Models.DeviceInformationModel device = deviceInformation;

    public bool IsConnected
    {
        get
        {
            if (master is null)
            {
                return false;
            }
            return true;

        }
    }

    public string Name => device.Name;

    public List<ContactsModel> Contacts => device.Contacts;

    public string Id => device.Number;

    public void Close()
    {
        if (master is not null)
        {
            master.Dispose();
        }
        master = null;
    }

    public void Connect()
    {
        try
        {
            if (device.Protocol == ProtocolEnum.ModbusTcp)
            {
                DeviceAddressModel deviceAddress = device.DeviceAddress;

                TcpClient client = new TcpClient(deviceAddress.Ip, deviceAddress.Port);

                var factory = new ModbusFactory();

                master = factory.CreateMaster(client);
            }
        }
        catch (Exception ex)
        {
            master = null;
            throw new Exception(ex.Message);
        }
    }

    public void Read(out List<FaultDataInformationModel> result)
    {
        try
        {
            //获取数据地址
            DataInformationModel addr = device.DataAddress;
            List<bool> res = new List<bool>();
            List<FaultDataInformationModel> faultDatas = new List<FaultDataInformationModel>();

            if (addr.FunctionCode == FunctionBlockEnum.Coils)
            {
                //0123456
                res = master.ReadCoils(addr.SlaveAddress, (ushort)(addr.StartAddress - 1), addr.NumberOfPoints).ToList();
                for (int i = 0; i < res.Count; i++)
                {
                    faultDatas.Add(new FaultDataInformationModel()
                    {
                        Value = res[i],
                        Message = addr.AlarmInformation[i],
                        Uid = addr.Uid[i],
                        Addr = (addr.StartAddress + i).ToString("N"),

                    });
                }
            }
            if (addr.FunctionCode == FunctionBlockEnum.Inputs)
            {
                res = master.ReadInputs(addr.SlaveAddress, (ushort)(addr.StartAddress - 1), addr.NumberOfPoints).ToList();
                for (int i = 0; i < res.Count; i++)
                {
                    faultDatas.Add(new FaultDataInformationModel()
                    {
                        Value = res[i],
                        Message = addr.AlarmInformation[i],
                        Uid = addr.Uid[i],
                        Addr = (addr.StartAddress + i).ToString("N"),

                    });
                }
            }

            result = faultDatas;
        }
        catch (Exception)
        {
            master = null;
            result = null;
        }

    }
}